package com.iflytek.aisol.audit.iflytek.strategy.manage.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.github.pagehelper.PageHelper;
import com.iflytek.aisol.audit.iflytek.strategy.manage.dto.ServerInstanceDTO;
import com.iflytek.aisol.audit.iflytek.strategy.manage.config.CustomException;
import com.iflytek.aisol.audit.iflytek.strategy.manage.constant.TableColumnInitConstant;
import com.iflytek.aisol.audit.iflytek.strategy.manage.entity.ChannelConfig;
import com.iflytek.aisol.audit.iflytek.strategy.manage.entity.ServerInstance;
import com.iflytek.aisol.audit.iflytek.strategy.manage.mapper.ServiceConfigMapper;
import com.iflytek.aisol.audit.iflytek.strategy.manage.mapper.fr.FrChannelConfigServerInstanceMapper;
import com.iflytek.aisol.audit.iflytek.strategy.manage.mapper.fr.FrGrayConfigServerInstanceMapper;
import com.iflytek.aisol.audit.iflytek.strategy.manage.query.PageDTO;
import com.iflytek.aisol.audit.iflytek.strategy.manage.query.ServicePageQuery;
import com.iflytek.aisol.audit.iflytek.strategy.manage.service.ServiceConfigService;
import com.iflytek.aisol.audit.iflytek.strategy.manage.utils.ConfigValidationUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


/**
 * CLassName: ServiceConfigServiceImpl
 * Description:
 * @author wuzhixiang
 * Date: 2024-12-28 16:11
 * Version: 1.0
 */
@Service
@RequiredArgsConstructor
public class ServiceConfigServiceImpl implements ServiceConfigService {

    private final ServiceConfigMapper serviceConfigMapper;
    private final ConfigValidationUtil configValidationUtil;
    private final FrGrayConfigServerInstanceMapper frGrayConfigServerInstanceMapper;
    private final FrChannelConfigServerInstanceMapper frChannelConfigServerInstanceMapper;
    /**
     * 新增服务配置接口
     */
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void add(ServerInstanceDTO serverInstanceDTO) {
        //新增时判断 instanceId 是否有已存在的配置
        String instanceId = serverInstanceDTO.getInstanceId();
        if(!serviceConfigMapper.findWithInstanceIdAndNoDeleteAndVersionMax(instanceId).isEmpty()){
            throw new CustomException("您配置的 instanceId 在数据库已经存在");
        }
        ServerInstance serverInstance = BeanUtil.toBean(serverInstanceDTO, ServerInstance.class);
        // 设置默认值
        serverInstance.setDeleted(TableColumnInitConstant.NOT_DELETED);
        serverInstance.setVersion(TableColumnInitConstant.INIT_VERSION);

        // 校验描述信息
        if (serverInstance.getDescription() == null) {
            throw new CustomException(TableColumnInitConstant.ERROR, "服务配置描述信息不能为空");
        }
        // 引擎类型
        // 前端匹配不上枚举，就报错
        String serverType = serverInstanceDTO.getServerType().getType();
        Object config = serverInstanceDTO.getConfig();
        /*if(!EnumChecker.isInServerType(serverType)){
            throw new CustomException(TableColumnInitConstant.ERROR,"输入的服务类型不合法");
        }
        // 查询引擎参数配置,校验 serverType 是否有效
        List<EngineParam> params = engineParamMapper.findByEngineType(serverType);
        Assert.notEmpty(params, "未找到引擎参数配置,配置的服务类型不存在");
        //1 根据params集合，取出该服务类型所支持的所有参数类型
        List<String> supportServiceTypes = params.stream().map(EngineParam::getParamType)
                .collect(Collectors.toList());

        //2 获取前端输入的 config
        String configJson = JSONUtil.toJsonStr(serverInstanceDTO.getConfig());
        Map<String, Object> config = JSONUtil.toBean(configJson, Map.class);

        // 遍历 Map 并获取每个字段的类型
        //Map<String, Object> fieldTypeMap = new HashMap<>();
        for (Map.Entry<String, Object> entry : config.entrySet()) {
            // 获取参数名字
            String fieldName = entry.getKey();
            // 获取参数类型
            Object fieldValue = entry.getValue();
            // 获取字段类型并转换成字符串形式
            String fieldType = ConfigValidationUtil.inferFieldType(fieldValue);
            if(!supportServiceTypes.contains(fieldType)){
                throw new CustomException(TableColumnInitConstant.ERROR,"字段 " + fieldName + " 类型不支持");
            }
            // 校验通过，保存到数据库
            EngineParam engineParam = new EngineParam();
            engineParam.setEngineType(serverType);
            engineParam.setParamName(fieldName);
            engineParam.setParamType(fieldType);
            engineParam.setInputType(fieldType);
            engineParamMapper.save(engineParam);
        }*/
        // 使用工具类校验并保存配置
        if (!ConfigValidationUtil.isInServerType(serverType)) {
            throw new CustomException("输入的server类型不合法");
        }
        // 从数据库引擎表检查serverConfig字段类型是否合法，合法将输入的字段类型写入引擎表
        configValidationUtil.validateConfig(config,serverType);

        serverInstance.setConfig(JSONUtil.toJsonStr(serverInstanceDTO.getConfig()));
        serverInstance.setServerType(serverType);
        //更新
        serviceConfigMapper.save(serverInstance);
    }

    /**
     * 修改服务配置接口
     * 先备份，再更新数据，最后写入旧数据
     *
     * @param id
     * @param serverInstanceDTO
     */
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void update(Long id, ServerInstanceDTO serverInstanceDTO) {
        // 先查询旧的数据
        ServerInstance existingServerConfig = serviceConfigMapper.getOne(id);
        Assert.notNull(existingServerConfig, "serverConfig 在数据库不存在");
        // 如果查出来的已经被删除则不可修改
        if(TableColumnInitConstant.DELETED.equals(existingServerConfig.getDeleted())){
            throw new CustomException("该条记录已经被删除了，不可修改");
        }
        // 复制旧数据，并清空 ID 以插入新记录
        ServerInstance oldServerInstance = new ServerInstance();
        BeanUtil.copyProperties(existingServerConfig,oldServerInstance);
        oldServerInstance.setId(null);
        oldServerInstance.setDeleted(TableColumnInitConstant.DELETED);
        serviceConfigMapper.save(oldServerInstance); // 先保存旧数据
        // 更新现有数据
        existingServerConfig.setConfig(JSONUtil.toJsonStr(serverInstanceDTO.getConfig()));
        existingServerConfig.setVersion(existingServerConfig.getVersion() + 1);
        existingServerConfig.setDescription(serverInstanceDTO.getDescription());
        existingServerConfig.setInstanceId(serverInstanceDTO.getInstanceId());
        serviceConfigMapper.save(existingServerConfig);

        //把旧数据的delete恢复
        ServerInstance ServerInstance = serviceConfigMapper.findById(oldServerInstance.getId()).get();
        ServerInstance.setDeleted(TableColumnInitConstant.NOT_DELETED);
        serviceConfigMapper.save(ServerInstance);
    }


    /**
     * 删除服务配置接口
     *
     * @param id
     */
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void delete(Long id) {
        // 删除时判断是否有级联使用
        if (!frGrayConfigServerInstanceMapper.findWithInstanceId(id).isEmpty()) {
            throw new CustomException("该server_instance_id在级联表frGrayConfigServerInstance已经配置过了，不能删除");
        }
        if(!frChannelConfigServerInstanceMapper.findWithInstanceId(id).isEmpty()){
            throw new CustomException("该server_instance_id在级联表frChannelConfigServerInstance已经配置过了，不能删除");
        }
        ServerInstance serverInstance = serviceConfigMapper.getOne(id);
        serverInstance.setDeleted(TableColumnInitConstant.DELETED);
        serviceConfigMapper.save(serverInstance);
    }

    /**
     * 分页查询
     *
     * @param
     * @return
     */
    @Override
    public PageDTO<ServerInstance> queryServicePage(ServicePageQuery query) {
        Integer pageNo = query.getPageNo();
        Integer pageSize = query.getPageSize();
        // 开启分页
        PageHelper.startPage(pageNo, pageSize);
        // 构建分页条件和排序字段
        // 判断是否有排序字段，如果没有就使用默认排序
        Pageable pageable;
        if (StrUtil.isNotBlank(query.getSortBy())) {
            pageable = PageRequest.of(pageNo - 1, pageSize,
                    query.getIsAsc() ? Sort.by(query.getSortBy()).ascending() : Sort.by(query.getSortBy()).descending());
        } else {
            // 默认排序，使用更新时间降序
            pageable = PageRequest.of(pageNo - 1, pageSize, Sort.by("updateTime").descending());
        }
        // 查询数据库
        Page<ServerInstance> page = serviceConfigMapper.findAllWithFilters(
                query.getInstanceId(), query.getVersion(), query.getDeleted(), pageable);
        // 封装成VO
        //List<ServiceVO> serviceVOS = BeanUtil.copyToList(page.getContent(), ServiceVO.class);
        // 构建分页DTO
        return new PageDTO<>(page.getTotalElements(), (long) page.getTotalPages(), page.getContent());
    }
    /*@Override
    public PageDTO<ServiceVO> queryServicePage(ServicePageQuery query) {
        Long version = query.getVersion();
        Long deleted = query.getDeleted();
        String instanceId = query.getInstanceId();
        // 构建分页条件和排序字段
        Page<ServerInstance> page = query.toMpPageDefaultSortByUpdateTimeDesc();
        Page<ServerInstance> page = Page.of(query.getPageNo(), query.getPageSize());
        if(StrUtil.isNotBlank(query.getSortBy())){
            page.addOrder(new OrderItem(query.getSortBy(),query.getIsAsc()));
        }else{
            // 排序字段为空，按照更新时间排序
            page.addOrder(new OrderItem("update_time",false));
        }

        // 分页查询
        Page<ServerInstance> p = lambdaQuery()
                .eq(instanceId != null, ServerInstance::getInstanceId, instanceId)
                .eq(version != null, ServerInstance::getVersion, version)
                .eq(deleted != null, ServerInstance::getDeleted, deleted)
                .page(page);
        // 封装成VO
        PageDTO<ServiceVO> dto = new PageDTO<>();
        //总条数
        dto.setTotal(p.getTotal());
        // 总页数
        dto.setPages(p.getPages());
        //当前页数据
        List<ServerInstance> records = p.getRecords();
        List<ServiceVO> serviceVOS = BeanUtil.copyToList(records, ServiceVO.class);
        dto.setRecords(serviceVOS);
        //返回结果
        return dto;
        //return PageDTO.of(p,ServiceVO.class);
        return PageDTO.of(p,ServerInstance->BeanUtil.copyProperties(ServerInstance,ServiceVO.class));
    }*/

}



